import JsSIP from 'jssip'


export default {
	data() {
	  return {
	    userAgent: null, // 用户代理实例
	    incomingSession: null,
			currentSession: null,
			outgoingSession: null,
	    password: "4bo9uys7", // 密码
	    serverIp: "acm.donnan.cn", // 服务器ip
			audio: null,
			meVideo: null,
			remoteVideo: null,
			localStream: null,
			constraints: {
				audio: true,
				video: {
					width: { max: 1280 },
					height: { max: 720 },
				},
			},
			myHangup: false,
	  }
	},
	computed: {
		ws_url() {
		  return `ws://${this.serverIp}:8088`;
		}
	},
	mounted() {
		this.audio = document.createElement('audio')
		this.audio.autoplay = true
		// this.audio.src = testMp3
		document.getElementById('audio-container').appendChild(this.audio)
		this.meVideo = document.createElement('video')
		this.meVideo.autoplay = true
		this.meVideo.playsinline = true
		// this.meVideo.src = testMp4
		document.getElementById('video-container').appendChild(this.meVideo)
		this.remoteVideo = document.createElement('video')
		this.remoteVideo.autoplay = true
		this.remoteVideo.playsinline = true
		// this.remoteVideo.src = testMp4
		document.getElementById('video-container').appendChild(this.remoteVideo)
		const styleObj = {
			width: '150px',
			'background-color': '#333',
			border: '2px solid blue',
			margin: '0 5px'
		}
		Object.keys(styleObj).forEach(key => {
			this.meVideo.style[key] = styleObj[key]
			this.remoteVideo.style[key] = styleObj[key]
		})
	},
	methods: {
		handleLogFlagChange(nV, oV) {
			nV ? JsSIP.debug.enable("JsSIP:*") : JsSIP.debug.disable("JsSIP:*");
			// this.log('logFlag', nV, oV)
			/* if(oV !== undefined) {
				this.log('logFlag', nV, oV)
			} */
		},
		handleUserExtenSionChange(nV, oV) {
			if(oV !== undefined) {
				// this.log('userExtenSion', nV, oV)
			}
		},
		handleTargetExtensionChange(nV, oV) {
			if(oV !== undefined) {
				// this.log('targetExtenSion', nV, oV)
			}
		},
		handleTestLocalStreamChange(nV, oV) {
			if(oV !== undefined) {
				// this.log('jsSipTestLocalStream', nV, oV)
				if(nV) {
					this.captureLocalMedia(() => {
						this.sendMsg('changeViewData', {
							key: 'hasLocalStream',
							value: true
						})
					}, (e) => {
						this.sendMsg('changeViewData', {
							key: 'jsSipTestLocalStream',
							value: false
						})
						this.sendMsg('notify', {
							type: 'error',
							message: "getUserMedia() error: " + e.name
						})
					})
				} else {
					this.stopLocalMedia()
					this.sendMsg('changeViewData', {
						key: 'jsSipTestLocalStream',
						value: false
					})
				}
			}
		},
		handleSipRegistedChange(nV, oV) {
			if(oV !== undefined) {
				if(nV) {
					this.registerUser()
				} else {
					this.unregisterUser()
				}
			}
		},
		handleCallByAudio(nV, oV) {
			if(oV !== undefined) {
				if(nV) {
					this.startCall(false)
				}
			}
		},
		handleCallByVideo(nV, oV) {
			if(oV !== undefined) {
				if(nV) {
					this.startCall(true)
				}
			}
		},
		handleJsSipHangupChange(nV, oV) {
			if(oV !== undefined) {
				if(nV) {
					this.hangUpCall()
				}
			}
		},
		captureLocalMedia(successCb, errCb) {
			console.log("Requesting local video & audio");
			navigator.mediaDevices
				.getUserMedia(this.constraints)
				.then((stream) => {
					console.log("Received local media stream");
					this.localStream = stream;

					// 连接本地麦克风
					if ("srcObject" in this.audio) {
						this.audio.srcObject = stream;
					} else {
						this.audio.src = window.URL.createObjectURL(stream);
					}
					// 如果有视频流，则连接本地摄像头
					if (stream.getVideoTracks().length > 0) {
						if ("srcObject" in this.meVideo) {
							this.meVideo.srcObject = stream;
						} else {
							this.meVideo.src = window.URL.createObjectURL(stream);
						}
					}
					successCb()
				})
				.catch((e) => errCb(e));
		},
		stopLocalMedia() {
			if (this.localStream) {
				this.localStream.getTracks().forEach((track) => track.stop());
				this.localStream = null;
				// 清空音频和视频的 srcObject
				this.clearMedia("audio");
				this.clearMedia("meVideo");
			}
		},
		clearMedia(mediaNameOrStream) {
			let mediaSrcObject = this[mediaNameOrStream].srcObject;
			if (mediaSrcObject) {
				let tracks = mediaSrcObject.getTracks();
				for (let i = 0; i < tracks.length; i++) {
					tracks[i].stop();
				}
			}
			this[mediaNameOrStream].srcObject = null;
		},
		registerUser() {
			const configuration = {
				sockets: [new JsSIP.WebSocketInterface(this.ws_url)],
				uri: `sip:${this.userExtension}@${this.serverIp};transport=ws`,
				password: this.password,
				contact_uri: `sip:${this.userExtension}@${this.serverIp};transport=ws`,
				display_name: this.userExtension,
				register: true, //指示启动时JsSIP用户代理是否应自动注册
				session_timers: false, //关闭会话计时器（根据RFC 4028）
			};
			this.userAgent = new JsSIP.UA(configuration);
			
			this.userAgent.on("connecting", (e) => console.log("WebSocket 连接中",e));
			this.userAgent.on("connected", (e) => console.log("WebSocket 连接成功",e));
			this.userAgent.on("disconnected", (e) =>
				console.log("WebSocket 断开连接",e)
			);
			this.userAgent.on("registered", (e) => {
				console.log("用户代理注册成功",e);
				// this.sendMsg('changeViewData', { key: 'isRegisted', value: true })
			});
			this.userAgent.on("unregistered", (e) => {
				console.log("用户代理取消注册",e);
				// this.sendMsg('changeViewData', { key: 'isRegisted', value: false })
			});
			this.userAgent.on("registrationFailed", (e) => {
				// this.sendMsg('notify', { type: 'error', message: '注册失败' })
                console.log("registrationFailed ",e);
			});
			
			this.userAgent.on("newRTCSession", (e) => {
				console.log("新会话: ", e);
				if (e.originator == "remote") {
					console.log("接听到来电");
					this.incomingSession = e.session;
					this.sipEventBind(e);
				} else {
					console.log("打电话");
					this.outgoingSession = e.session;

					this.outgoingSession.on("connecting", (data) => {
						console.info("onConnecting - ", data.request);
						this.currentSession = this.outgoingSession;
						this.sendMsg('changeViewData', { key: 'hasCurrentSession', value: true })
						this.outgoingSession = null;
					});
					
					this.outgoingSession.connection.addEventListener("track", (event) => {
						console.info("Received remote track:", event.track);
						this.trackHandle(event.track, event.streams[0]);
					});

					//连接到信令服务器，并恢复以前的状态，如果以前停止。重新开始时，如果UA配置中的参数设置为register:true，则向SIP域注册。
					this.userAgent.start();
					console.log("用户代理启动");
				}
			})
			
			//连接到信令服务器，并恢复以前的状态，如果以前停止。重新开始时，如果UA配置中的参数设置为register:true，则向SIP域注册。
			this.userAgent.start();
			console.log("用户代理启动");
		},
		startCall(isVideo = false) {
			if (this.userAgent) {
				try {
					const eventHandlers = {
						progress: (e) => console.log("call is in progress"),
						failed: (e) => {
							console.error(e);
							this.sendMsg('notify', {
								type: 'error',
								message: `call failed with cause: ${e.cause}`
							})
						},
						ended: (e) => {
							this.endedHandle();
							console.log(`call ended with cause: ${e.cause}`);
						},
						confirmed: (e) => console.log("call confirmed"),
					};
					console.log("this.userAgent.call");
					this.outgoingSession = this.userAgent.call(
						`sip:${this.targetExtension}@${this.serverIp}`, // :5060
						{
							mediaConstraints: { audio: true, video: isVideo },
							eventHandlers,
						}
					);
				} catch (error) {
					this.sendMsg('notify', {
						type: 'error',
						message: '呼叫失败'
					})
					console.error("呼叫失败：", error);
				}
			} else {
				this.sendMsg('notify', {
					type: 'error',
					message: '用户代理未初始化'
				})
			}
		},
		sipEventBind(remotedata, callbacks) {
			//接受呼叫时激发
			remotedata.session.on("accepted", () => {
				console.log("onAccepted - ", remotedata);
				if (remotedata.originator == "remote" && this.currentSession == null) {
					this.currentSession = this.incomingSession;
					this.sendMsg('changeViewData', { key: 'hasCurrentSession', value: true })
					this.incomingSession = null;
					console.log("setCurrentSession：", this.currentSession);
				}
			});

			//在将远程SDP传递到RTC引擎之前以及在发送本地SDP之前激发。此事件提供了修改传入和传出SDP的机制。
			remotedata.session.on("sdp", (data) => {
				console.log("onSDP, type - ", data.type, " sdp - ", data.sdp);
			});

			//接收或生成对邀请请求的1XX SIP类响应（>100）时激发。该事件在SDP处理之前触发（如果存在），以便在需要时对其进行微调，甚至通过删除数据对象中响应参数的主体来删除它
			remotedata.session.on("progress", () => {
				console.log(remotedata);
				console.log("onProgress - ", remotedata.originator);
				if (remotedata.originator == "remote") {
					console.log("onProgress, response - ", remotedata.response);
					//answer设置的自动接听
					//RTCSession 的 answer 方法做了自动接听。实际开发中，你需要弹出一个提示框，让用户选择是否接听

					const isVideoCall = remotedata.request.body.includes("m=video");
					const flag = confirm(`检测到${remotedata.request.from.display_name}的${isVideoCall ? "视频" : "语音"}来电，是否接听？`);
					if(!flag) {
						this.hangUpCall();
						return;
					} else {
						//如果同一电脑两个浏览器测试则video改为false,这样被呼叫端可以看到视频，两台电脑测试让双方都看到改为true
						remotedata.session.answer({
							mediaConstraints: { audio: true, video: isVideoCall },
							// mediaStream: this.localStream,
						});
					}
				}
			});

			//创建基础RTCPeerConnection后激发。应用程序有机会通过在peerconnection上添加RTCDataChannel或设置相应的事件侦听器来更改peerconnection。
			remotedata.session.on("peerconnection", () => {
				console.log("onPeerconnection - ", remotedata.peerconnection);

				if (remotedata.originator == "remote" && this.currentSession == null) {
					//拿到远程的音频流
					/* remotedata.session.connection.addEventListener(
						"addstream",
						(event) => {
							console.info("Received remote stream:", event.stream);
							this.streamHandle(event.stream);
						}
					); */
					remotedata.session.connection.addEventListener("track", (event) => {
						console.info("Received remote track:", event.track);
						this.trackHandle(event.track, event.streams[0]);
					});
				}
			});

			//确认呼叫后激发
			remotedata.session.on("confirmed", () => {
				console.log("onConfirmed - ", remotedata);
				if (remotedata.originator == "remote" && this.currentSession == null) {
					this.currentSession = this.incomingSession;
					this.sendMsg('changeViewData', { key: 'hasCurrentSession', value: true })
					this.incomingSession = null;
					console.log("setCurrentSession - ", this.currentSession);
				}
			});

			// 挂断处理
			remotedata.session.on("ended", () => {
				this.endedHandle();
				console.log("call ended：", remotedata);
			});

			remotedata.session.on("failed", (e) => {
				this.sendMsg('notify', { type: 'error', message: '会话失败' })
				console.error("会话失败：", e);
			});
		},
		unregisterUser() {
			console.log("取消注册");
			this.userAgent.unregister();
			this.sendMsg('changeViewData', { key: 'isRegisted', value: false })
			this.sendMsg('changeViewData', { key: 'userExtension', value: '' })
			this.sendMsg('changeViewData', { key: 'targetExtension', value: '' })
		},
		trackHandle(track, stream) {
			const showVideo = () => {
				navigator.mediaDevices
					.getUserMedia({
						...this.constraints,
						audio: false, // 不播放本地声音
					})
					.then((stream) => {
						this.meVideo.srcObject = stream;
					})
					.catch((error) => {
						this.sendMsg('notify', {
							type: 'error',
							message: `${error.name}：${error.message}`
						})
					});
			};
			// 根据轨道类型选择播放元素
			if (track.kind === "video") {
				// 使用 video 元素播放视频轨道
				this.remoteVideo.srcObject = stream;
				showVideo();
			} else if (track.kind === "audio") {
				// 使用 audio 元素播放音频轨道
				this.audio.srcObject = stream;
			}
		},
		endedHandle() {
			this.clearMedia("meVideo");
			this.clearMedia("remoteVideo");
			this.clearMedia("audio");
			if (this.myHangup) {
				this.sendMsg('notify', { type: 'success', message: '通话结束' })
			} else {
				this.sendMsg('notify', { type: 'warning', message: '对方已挂断!' })
			}
			this.myHangup = false;

			this.currentSession = null;
			this.sendMsg('changeViewData', { key: 'hasCurrentSession', value: false })
			this.sendMsg('changeViewData', { key: 'jsSipCallByVideo', value: false })
			this.sendMsg('changeViewData', { key: 'jsSipCallByAudio', value: false })
		},
		hangUpCall() {
			this.myHangup = true;
			this.outgoingSession = this.userAgent.terminateSessions();
			this.currentSession = null;
			this.sendMsg('changeViewData', { key: 'hasCurrentSession', value: false })
			this.sendMsg('changeViewData', { key: 'jsSipHangup', value: false })
		},
		// 日志
		log(key, nV, oV) {
			console.log(`renderjs：${key} 改变`);
			console.log(`${key} 新值：`, nV);
			console.log(`${key} 旧值：`, oV);
		},
		// 向视图层发送消息
		sendMsg(msg, data) {
			// 向页面传参
			// console.log('renderjs sendMsg：');
			// console.log(msg, data);
			
			this.$ownerInstance.callMethod('reciveMessage', {
				msg,
				data
			})
		},
	}
}
